package com.chat.common.handler.global_exception;

import cn.hutool.http.HttpStatus;
import com.chat.common.common.exception.BaseException;
import com.chat.common.vo.R;
import jakarta.validation.ConstraintViolation;
import jakarta.validation.ConstraintViolationException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.io.IOException;
import java.util.stream.Collectors;

/**
 * 全局异常
 */
@RestControllerAdvice
@Slf4j
public class GlobalExceptionHandler {
    /**
     * 捕获业务异常（运行时异常）
     * @return
     */
    @ExceptionHandler(value = BaseException.class)
    @ResponseBody
    public R<Object> exceptionHandler(BaseException ex){
        log.error("异常信息：{}", ex.getMessage());
        return R.failed(ex.getStatusCode().value(),ex.getMessage());
    }

    /**
     * 处理 MethodArgumentNotValidException 异常
     * 这个异常通常在使用 @Valid 注解的参数验证失败时抛出
     * @param ex MethodArgumentNotValidException 异常对象
     * @return 包含错误信息的响应
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseBody
    public R<Object> handleValidationExceptions(MethodArgumentNotValidException ex) {
        log.error("异常信息：{}", ex.getMessage());
        String errorMessage = ex.getBindingResult().getAllErrors().stream()
                .map(ObjectError::getDefaultMessage)
                .collect(Collectors.joining(", "));
        return R.failed(400,errorMessage);
    }

    /**
     * 处理 ConstraintViolationException 异常
     * 这个异常在参数校验过程中发现约束条件被违反时抛出
     * @param ex ConstraintViolationException 异常对象
     * @return 包含错误信息的响应
     */
    @ExceptionHandler(ConstraintViolationException.class)
    @ResponseBody
    public R<Object> handleConstraintViolationExceptions(ConstraintViolationException ex) {
        log.error("异常信息：{}", ex.getMessage());
        String errorMessage = ex.getConstraintViolations().stream()
                .map(ConstraintViolation::getMessage)
                .collect(Collectors.joining(", "));
        return R.failed(400,errorMessage);
    }

    /**
     * 处理 BindException 异常
     * 这个异常在使用 @ModelAttribute 的参数验证失败时抛出
     * @param ex BindException 异常对象
     * @return 包含错误信息的响应
     */
    @ExceptionHandler(BindException.class)
    @ResponseBody
    public R<Object> handleBindException(BindException ex) {
        log.error("异常信息：{}", ex.getMessage());
        String errorMessage = ex.getBindingResult().getAllErrors().stream()
                .map(ObjectError::getDefaultMessage)
                .collect(Collectors.joining(", "));
        return R.failed(400, errorMessage);
    }

    /**
     * IO异常
     * @param ex
     * @return
     */
    @ExceptionHandler(IOException.class)
    @ResponseBody
    public R<Object> handleIOExceptions(IOException ex) {
        log.error("异常信息：{}", ex.getMessage());
        return R.failed(HttpStatus.HTTP_BAD_REQUEST, "IO操作异常Error:" + ex.getMessage());
    }

}
